//
// Unihan Input Method
//
// Copyright © 2002-2007 Sun Wah Linux Ltd.
//
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
// USA
//
// $Id: tabinfo.c 757 2007-05-10 08:19:31Z roger $
//

#include <stdio.h>
#include <string.h>
#include <iconv.h>
#include <stdlib.h>

#include <SWTable.h>

PEKey pekey[0x60];
FastIdx fastidx[0x60];
KeyValTable *keyvaltab;
char *keylist;
char *vallist;
iconv_t iconvd;

unsigned long hints;

/* Function prototypes */
int keycmp(const char *, const char *);
int find_candidate(const char *, int *, int *);
void test_preedit(const char *);

int
keycmp(const char *str1, const char *str2)
{
	return strncmp(str1, str2, strlen(str1));
}

int
find_candidate(const char *pe, int *low, int *high)
{
	int l, u, i, tmp;
	KeyValTable *keyval;

	l = *low;
	u = *high;

	while (1) {
		if (u < l) {
			*high = *low = -1;
			return 0;
		}

		i = (l + u)/2;

		keyval = &keyvaltab[i];
		tmp = keycmp(pe + 1, keylist+(keyval->keyoff) + 1);

		if (tmp < 0)
			u = i - 1;
		else if (tmp > 0)
			l = i + 1;
		else
			break;
	}
	l = i - 1; u = i + 1;
	while (l > 0) {
		keyval = &keyvaltab[l];
		tmp = keycmp(pe, keylist+(keyval->keyoff));
		if (tmp != 0)
			break;
		l--;
	}
	l++;
	while (u < num_val) {
		keyval = &keyvaltab[u];
		tmp = keycmp(pe, keylist+(keyval->keyoff));
		if (tmp != 0)
			break;
		u++;
	}

	*low = l;
	*high = u;
	return 1;
}

void
test_preedit(const char *preedit)
{
	int i, len;
	char *tmp, *tmp2;
	char *pename = NULL, *pename2 = NULL;
	int inb, outb;
	int l, h;

	pename = malloc(7); memset(pename, 0, 7);
	
	printf("\nentered: (%s) ", preedit);
	len = strlen(preedit);
	for (i = 0; i < len; i++) {
		tmp2 = tmp = pekey[idx(preedit[i])].name;
		if (tmp[0] == '\0') {
			printf(" * Invalid preedit key!\n");
			free(pename);
			return;
		}
		inb = strlen(tmp);
		outb = 7;
		pename2 = pename;
		iconv(iconvd, &tmp2, &inb, &pename2, &outb);
		*pename2 = 0;
		printf("%s", pename);
	}
	printf("\n");
	free(pename);

	l = fastidx[idx(preedit[0])].offset;
	h = fastidx[idx(preedit[0])+1].offset - 1;

	printf("according to fastidx, '%c' starts at %d and ends at %d \n",
		preedit[0], l, h);
	printf("in the codetable\n");

	printf("find_candidate() ");
	if (!find_candidate(preedit, &l, &h)) {
		printf("did not find any candidates\n");
	} else {
		printf("found %d candidates\n", h-l);
		for (i = l; i < h; i++) {
			KeyValTable *kv = &keyvaltab[i];

			tmp2 = tmp = vallist+(kv->valoff);
			outb = inb = strlen(tmp);
			pename2 = pename = malloc(inb);
			iconv(iconvd, &tmp2, &inb, &pename2, &outb);
			*pename2 = 0;
			printf("%s\t%s\n", keylist+(kv->keyoff), pename);
			free(pename);
		}
	}
	
	return;
}

int 
main(int argc, char *argv[])
{
	FILE *tabfile;
	char *tmp = NULL, *tmp_p = NULL;
	char *b5_cname = NULL, *b5_cname_p = NULL;
	int inb, outb;
	int idx_key_tbl_len, idx_val_tbl_len;
	
	if (argc < 2) {
		printf("which file?\n");
		return 1;
	}

	tabfile = fopen(argv[1], "r");
	if (!tabfile) {
		printf("can't open\n");
		return 1;
	}

	tmp = malloc(21); memset(tmp, 0, 21);

	fread(tmp, strlen(SIG)+1, 1, tabfile);
	if (!strncmp(SIG, tmp, strlen(SIG))) {
		printf("Signature good\n");
	} else {
		printf("Bad signature\n");
		return 1;
	}
	
	//iconvd = iconv_open("big5hkscs", "utf-8");
	iconvd = iconv_open("utf-8", "utf-8");

	b5_cname = malloc(21); memset(b5_cname, 0, 21);

	fread(tmp, 20, 1, tabfile);
	printf("ename: %s\n", tmp);
	fread(tmp, 20, 1, tabfile);
	
	inb = strlen(tmp);
	outb = 20;
	tmp_p = tmp;
	b5_cname_p = b5_cname;
	iconv(iconvd, &tmp_p, &inb, &b5_cname_p, &outb);
	*b5_cname_p = '\0';
	printf("cname: %s\n", b5_cname);
	free(b5_cname);

	fread(&hints, sizeof(hints), 1, tabfile);
	printf("hints: %ld\n", hints);
	if (hints & SHOW_AS_U_GO) {
		printf("\tSHOW_AS_U_GO\n");
	}
	
	fread(&num_key, sizeof(int), 1, tabfile);
	printf("num_key: %d\n", num_key);
	fread(&num_val, sizeof(int), 1, tabfile);
	printf("num_val: %d\n", num_val);
	fread(&idx_key_tbl_len, sizeof(int), 1, tabfile);
	printf("idx_key_tbl_len: %d\n", idx_key_tbl_len);
	fread(&idx_val_tbl_len, sizeof(int), 1, tabfile);
	printf("idx_val_tbl_len: %d\n", idx_val_tbl_len);

	if (argc > 2) {
		fread(pekey, sizeof(PEKey), 0x60, tabfile);
		fread(fastidx, sizeof(FastIdx), 0x60, tabfile);

		keyvaltab = (KeyValTable*)malloc(sizeof(KeyValTable)*num_val);
		fread(keyvaltab, sizeof(KeyValTable), num_val, tabfile);

		keylist = (char*)malloc(sizeof(char)*idx_key_tbl_len);
		vallist = (char*)malloc(sizeof(char)*idx_val_tbl_len);
		fread(keylist, sizeof(char), idx_key_tbl_len, tabfile);
		fread(vallist, sizeof(char), idx_val_tbl_len, tabfile);
		
		test_preedit(argv[2]);

		free(keyvaltab);
		free(keylist);
		free(vallist);
	}

	fclose(tabfile);
	
	iconv_close(iconvd);
	
	return 0;
}

// vi:ts=4:nowrap:cin:expandtab
